package com.luxus.app;

import java.util.List;

import com.android.camera.debug.Log;
import com.android.camera.one.CameraId;
import com.android.camera.one.OneCamera.Facing;
import com.android.camera.one.OneCameraAccessException;
import com.android.camera.one.OneCameraCharacteristics;
import com.android.camera.one.OneCameraCharacteristics.FaceDetectMode;
import com.android.camera.one.OneCameraCharacteristics.SupportedHardwareLevel;
import com.android.camera.one.OneCameraException;
import com.android.camera.one.OneCameraManager;
import com.android.camera.one.OneCameraModule;
import com.android.camera.one.config.OneCameraAvailableCapabilities;
import com.android.camera.one.config.OneCameraAvailableCapabilities.RequestCapabilities;
import com.android.camera.util.Size;
import com.luxus.cdcam.R;
import com.luxus.dev.GyroOperations;

import android.app.Activity;
import android.content.Intent;
import android.graphics.ImageFormat;
import android.hardware.Sensor;
import android.hardware.SensorManager;
import android.os.Bundle;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.EditText;
import android.widget.LinearLayout;
import android.widget.RadioButton;
import android.widget.RadioGroup;
import android.widget.TextView;
import android.widget.ToggleButton;

public class StartActivity extends Activity {
	private static final Log.CTag TAG = new Log.CTag("StartActivity");
	
	OneCameraManager mOneCameraManager;
	
	private RadioGroup start_use_surface;
	private LinearLayout start_main_cam;
	private ToggleButton[] start_main_cam_array;
	private ToggleButton current_main_cam;
	private LinearLayout start_sub_cam;
	private ToggleButton[] start_sub_cam_array;
	private ToggleButton current_sub_cam;
	
	private LinearLayout start_create_config;
	private CheckBox start_use_reprocess;
	private RadioGroup start_use_capture_level;
	private RadioButton start_use_level3;
	private RadioButton start_use_zsl;
	private RadioButton start_use_limited_yuv;
	private RadioButton start_use_limited_jpeg;
	private RadioButton start_use_legacy_jpeg;
	
	private LinearLayout start_preview_config;
	private LinearLayout start_gyro_config;
	private RadioGroup start_use_gyro_level;
	private LinearLayout start_flash_config;
	private RadioGroup start_use_flash_level;
	private CheckBox start_use_facedct;
	
	private LinearLayout start_edit_config;
	private TextView start_use_show_previewsize;
	private EditText start_use_previewsize_edit;
	private TextView start_use_show_picturesize;
	private EditText start_use_picturesize_edit;
	private EditText start_use_screenlight_edit;
	
	private Button mStartVivoCamera;
	
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_start);
		
		findAllViews();
		initAllViews();
	}
	
	@Override
	public void onResume() {
		super.onResume();
	}
	
	private void findAllViews() {
		start_use_surface = (RadioGroup)this.findViewById(R.id.start_use_surface);
		start_main_cam = (LinearLayout)this.findViewById(R.id.start_main_cam);
		start_sub_cam = (LinearLayout)this.findViewById(R.id.start_sub_cam);
		
		start_create_config = (LinearLayout)this.findViewById(R.id.start_create_config);
		start_use_reprocess = (CheckBox)this.findViewById(R.id.start_use_reprocess);
		start_use_capture_level = (RadioGroup)this.findViewById(R.id.start_use_capture_level);
		start_use_level3 = (RadioButton)this.findViewById(R.id.start_use_level3);
		start_use_zsl = (RadioButton)this.findViewById(R.id.start_use_zsl);
		start_use_limited_yuv = (RadioButton)this.findViewById(R.id.start_use_limited_yuv);
		start_use_limited_jpeg = (RadioButton)this.findViewById(R.id.start_use_limited_jpeg);
		start_use_legacy_jpeg = (RadioButton)this.findViewById(R.id.start_use_legacy_jpeg);
		
		start_preview_config = (LinearLayout)this.findViewById(R.id.start_preview_config);
		start_use_facedct = (CheckBox)this.findViewById(R.id.start_use_facedct);
		start_gyro_config = (LinearLayout)this.findViewById(R.id.start_gyro_config);
		start_use_gyro_level = (RadioGroup)this.findViewById(R.id.start_use_gyro_level);
		start_flash_config = (LinearLayout)this.findViewById(R.id.start_flash_config);
		start_use_flash_level = (RadioGroup)this.findViewById(R.id.start_use_flash_level);
		
		start_edit_config = (LinearLayout)this.findViewById(R.id.start_edit_config);
		start_use_show_previewsize = (TextView)this.findViewById(R.id.start_use_show_previewsize);
		start_use_previewsize_edit = (EditText)this.findViewById(R.id.start_use_previewsize_edit);
		start_use_show_picturesize = (TextView)this.findViewById(R.id.start_use_show_picturesize);
		start_use_picturesize_edit = (EditText)this.findViewById(R.id.start_use_picturesize_edit);
		start_use_screenlight_edit = (EditText)this.findViewById(R.id.start_use_screenlight_edit);
		
		mStartVivoCamera = (Button)this.findViewById(R.id.start_camera);
	}
	
	private ToggleButton[] initCamButtons(boolean main, CameraId[] backCameras, CameraId[] frontCameras, ViewGroup group) {
		int backCount = (backCameras == null) ? 0 : backCameras.length;
		int frontCount= (frontCameras == null) ? 0 : frontCameras.length;
		ToggleButton[] cam_array = new ToggleButton[backCount + frontCount];
		int index = 0;
		for (int i = 0; i < backCount; ++i) {
			ToggleButton button = new ToggleButton(this);
			button.setVisibility(View.VISIBLE);
			button.setOnClickListener(new CamListener(main, backCameras[i], Facing.BACK));
			button.setTag(backCameras[i]);
			String text = new String("back"+backCameras[i].getValue());
			button.setTextOff(text);
			button.setTextOn(text);
			button.setText(text);
			group.addView(button);
			cam_array[index++] = button;
		}
		
		for (int i = 0; i < frontCount; ++i) {
			ToggleButton button = new ToggleButton(this);
			button.setVisibility(View.VISIBLE);
			button.setOnClickListener(new CamListener(main, frontCameras[i], Facing.FRONT));
			button.setTag(frontCameras[i]);
			String text = new String("front"+frontCameras[i].getValue());
			button.setTextOff(text);
			button.setTextOn(text);
			button.setText(text);
			group.addView(button);
			cam_array[index++] = button;
		}
		return cam_array;
	}
	
	private void initAllViews() {
		try {
			mOneCameraManager = OneCameraModule.provideOneCameraManager();			
			CameraId[] backCameras = mOneCameraManager.getCameraIdsFacing(Facing.BACK);
			CameraId[] frontCameras= mOneCameraManager.getCameraIdsFacing(Facing.FRONT);
			start_main_cam_array = initCamButtons(true, backCameras, frontCameras, start_main_cam);
			current_main_cam = start_main_cam_array[0];
			current_main_cam.setChecked(true);
			start_sub_cam_array = initCamButtons(false, backCameras, frontCameras, start_sub_cam);
			current_sub_cam = start_sub_cam_array[0];
			current_sub_cam.setChecked(true);
			
			start_create_config.setVisibility(View.VISIBLE);
			start_preview_config.setVisibility(View.VISIBLE);
			start_edit_config.setVisibility(View.VISIBLE);
			configureChangeViews(true, current_main_cam);
		} catch (OneCameraException e) {
			
		}
		
		mStartVivoCamera.setOnClickListener(new View.OnClickListener() {
			@Override
			public void onClick(View v) {
				// TODO Auto-generated method stub
				updateFeatureConfig();
				Intent intent = new Intent();
				intent.setClass(getApplication(), CDCamActivity.class);
				StartActivity.this.startActivity(intent);
			}
		});
	}
	
	private void updateFeatureConfig() {
		//----Display Controller
		if (start_use_surface.getCheckedRadioButtonId() 
				== R.id.start_use_nodisplay) {
			FeatureConfig.useSurfaceType = FeatureConfig.WITH_NODISPLAY;
		} else if (start_use_surface.getCheckedRadioButtonId() 
				== R.id.start_use_textureview) {
			FeatureConfig.useSurfaceType = FeatureConfig.WITH_TEXTUREVIEW;
		} else {
			FeatureConfig.useSurfaceType = FeatureConfig.WITH_SURFACEVIEW;
		}
		//----Camera Device
		CameraId cameraId = (CameraId)current_main_cam.getTag();
		FeatureConfig.mainCameraId = cameraId;
		CameraId subId = (CameraId)current_sub_cam.getTag();
		if (cameraId.equals(subId)) {
			FeatureConfig.subCameraId = null; 
		} else {
			FeatureConfig.subCameraId = subId; 
		}
		//----Reprocessable
		FeatureConfig.useReprocess = start_use_reprocess.isChecked() 
				&& start_use_reprocess.getVisibility() == View.VISIBLE;
		//----Capture Level
		switch (start_use_capture_level.getCheckedRadioButtonId()) {
		case R.id.start_use_level3:
		case R.id.start_use_zsl:
			FeatureConfig.useLevel = 1;
			break;
		case R.id.start_use_legacy_jpeg:
			FeatureConfig.useLevel = 2;
			break;
		case R.id.start_use_limited_jpeg:
			FeatureConfig.useLevel = 3;
			break;
		case R.id.start_use_limited_yuv:
			FeatureConfig.useLevel = 4;
			break;
		default:
			if (start_use_level3.getVisibility() == View.VISIBLE 
					|| start_use_zsl.getVisibility() == View.VISIBLE) {
				FeatureConfig.useLevel = 1;
			} else if (start_use_limited_yuv.getVisibility() == View.VISIBLE) {
				FeatureConfig.useLevel = 4;
			} else if (start_use_limited_jpeg.getVisibility() == View.VISIBLE) {
				FeatureConfig.useLevel = 3;
			} else if (start_use_legacy_jpeg.getVisibility() == View.VISIBLE) {
				FeatureConfig.useLevel = 2;
			} else {
				FeatureConfig.useLevel = -1;
			}
			break;
		}
		//----Face Detect
		FeatureConfig.enableFaceDct = start_use_facedct.isChecked();
		//----Gyro
		switch (start_use_gyro_level.getCheckedRadioButtonId()) {
		case R.id.start_use_gyro_fast:
			FeatureConfig.gyroMode = GyroOperations.GYRO_FASTEST;
			break;
		case R.id.start_use_gyro_game:
			FeatureConfig.gyroMode = GyroOperations.GYRO_GAME;
			break;
		case R.id.start_use_gyro_ui:
			FeatureConfig.gyroMode = GyroOperations.GYRO_UI;
			break;
		case R.id.start_use_gyro_normal:
			FeatureConfig.gyroMode = GyroOperations.GYRO_NORMAL;
			break;
		default:
			FeatureConfig.gyroMode = GyroOperations.GYRO_NONE;
			break;
		}
		//----Flash
		switch (start_use_flash_level.getCheckedRadioButtonId()) {
		case R.id.start_use_flash_off:
			FeatureConfig.useFlashSetting = "off";
			break;
		case R.id.start_use_flash_auto:
			FeatureConfig.useFlashSetting = "auto";
			break;
		case R.id.start_use_flash_on:
			FeatureConfig.useFlashSetting = "on";
			break;
		default:
			FeatureConfig.useFlashSetting = "off";
			break;
		}
		if (start_flash_config.getVisibility() != View.GONE) {
			FeatureConfig.useFlashSetting = "off";
		}
		
		//----Preview Size
		String previewSize = start_use_previewsize_edit.getEditableText().toString();
		String pictureSize = start_use_picturesize_edit.getEditableText().toString();
		FeatureConfig.usePreviewSize = getEditSize(previewSize, new Size(4, 3));
		FeatureConfig.usePictureSize = getEditSize(pictureSize, new Size(4, 3));
		
		String screenLight = start_use_screenlight_edit.getEditableText().toString();
		int lightLevel = getEditInt(screenLight, 50);
		if (lightLevel > 100) {
			lightLevel = 100;
		} else if (lightLevel < 0){
			lightLevel  = 0;
		}
		FeatureConfig.useScreenLight = lightLevel;
	}
	
	private class CamListener implements View.OnClickListener {
		private final CameraId mId;
		private final Facing mFacing;
		private final boolean mMain;
		
		public CamListener(boolean main, CameraId id, Facing facing) {
			mMain = main;
			mId = id;
			mFacing = facing;
		}
		
		public void onClick(View view) {
			configureChangeViews(mMain, view);
		}
	}
	
	private void configureChangeViews(boolean main, View view) {
		boolean checked = ((ToggleButton)view).isChecked();
		if (!main) {
			for (ToggleButton button : start_sub_cam_array) {
				button.setChecked(false);
			}
			if (!checked) {
				current_sub_cam = start_sub_cam_array[0];
				current_sub_cam.setChecked(true);
			} else {
				current_sub_cam = ((ToggleButton)view);
				current_sub_cam.setChecked(checked);
			}
		} else {
			for (ToggleButton button : start_main_cam_array) {
				button.setChecked(false);
			}
			if (!checked) {
				current_main_cam = start_main_cam_array[0];
				current_main_cam.setChecked(true);
			} else {
				current_main_cam = ((ToggleButton)view);
				current_main_cam.setChecked(checked);
			}
		}
		
		CameraId mainId = (CameraId)current_main_cam.getTag();
		CameraId subId = (CameraId)current_sub_cam.getTag();
		boolean dualCam = false;
		if (!mainId.equals(subId)) {
			dualCam = true;
		}
		
		try {
			OneCameraCharacteristics oneCharacteristics = 
					mOneCameraManager.getOneCameraCharacteristics(mainId);
			
			List<Size> previewSizes = oneCharacteristics.getSupportedPreviewSizes();
			StringBuilder preview = new StringBuilder();
			for (Size size : previewSizes) {
				preview.append(size.getWidth());
				preview.append("x");
				preview.append(size.getHeight());
				preview.append(";");
			}
			start_use_show_previewsize.setText(preview.toString());
			
			List<Size> highResSizes = oneCharacteristics.getHighResolutionPictureSizes(ImageFormat.JPEG);
			StringBuilder picture = new StringBuilder();
			for (Size size : highResSizes) {
				picture.append(size.getWidth());
				picture.append("x");
				picture.append(size.getHeight());
				picture.append("|");
			}
			List<Size> normalSizes = oneCharacteristics.getDefaultPictureSizes(ImageFormat.JPEG);
			for (Size size : normalSizes) {
				picture.append(size.getWidth());
				picture.append("x");
				picture.append(size.getHeight());
				picture.append(";");
			}
			start_use_show_picturesize.setText(picture.toString());
			
			OneCameraAvailableCapabilities availableCapabilities = 
	        		new OneCameraAvailableCapabilities(oneCharacteristics);
	        boolean reprocessable = availableCapabilities.isSupport(RequestCapabilities.YUV_REPROCESSING);
			start_use_reprocess.setVisibility((dualCam || !reprocessable) ? View.GONE : View.VISIBLE);
			SupportedHardwareLevel level = oneCharacteristics.getSupportedHardwareLevel();
			start_use_level3.setVisibility(View.VISIBLE);
			start_use_zsl.setVisibility(View.VISIBLE);
			start_use_limited_yuv.setVisibility(View.VISIBLE);
			start_use_limited_jpeg.setVisibility(View.VISIBLE);
			start_use_legacy_jpeg.setVisibility(View.VISIBLE);
			if (dualCam) {
				start_use_level3.setVisibility(View.GONE);
				start_use_zsl.setVisibility(View.GONE);
			} else if (level == SupportedHardwareLevel.FULL) {
				start_use_level3.setVisibility(View.GONE);
			} else if (level == SupportedHardwareLevel.LIMITED) {
				start_use_level3.setVisibility(View.GONE);
				start_use_zsl.setVisibility(View.GONE);
			} else if (level == SupportedHardwareLevel.LEGACY) {
				start_use_level3.setVisibility(View.GONE);
				start_use_zsl.setVisibility(View.GONE);
				start_use_limited_yuv.setVisibility(View.GONE);
				start_use_limited_jpeg.setVisibility(View.GONE);
			}
			
			SensorManager sensorManager = (SensorManager) getSystemService(Activity.SENSOR_SERVICE);
			Sensor gyro = sensorManager.getDefaultSensor(Sensor.TYPE_GYROSCOPE);
			start_gyro_config.setVisibility(gyro == null ? View.GONE : View.VISIBLE);
			boolean flashSupported = oneCharacteristics.isFlashSupported();
			start_flash_config.setVisibility(!flashSupported ? View.GONE : View.VISIBLE);
			
			List<FaceDetectMode> faceDct = oneCharacteristics.getSupportedFaceDetectModes();
			boolean faceDctSupport = false;
			for (FaceDetectMode mode : faceDct) {
				if (mode == FaceDetectMode.FULL || mode == FaceDetectMode.SIMPLE) {
					faceDctSupport = true;
					break;
				}
			}
			start_use_facedct.setVisibility(!faceDctSupport ? View.GONE : View.VISIBLE);
			
			mStartVivoCamera.setText(dualCam ? R.string.start_dual_camera : R.string.start_camera);
		} catch (OneCameraAccessException ex) {
			
		}
	}
	
	private static Size getEditSize(final String editString, Size defaultSize) {
		if (editString == null || editString.equals("")) {
			return defaultSize;
		} else {
			int index = editString.indexOf("x");
			if (index == -1) {
				return defaultSize;
			} else {
				String widthStr = editString.substring(0, index);
				String heightStr= editString.substring(index+1, editString.length());
				try {
					int width = Integer.parseInt(widthStr);
					int height= Integer.parseInt(heightStr);
					return new Size(width, height);
				} catch (Exception ex) {
					return defaultSize;
				}
			}
		}
	}
	
	private static int getEditInt(String editString, int defaultValue) {
		if (editString == null || editString.equals("")) {
			return defaultValue;
		} else {
			try {
				int value = Integer.parseInt(editString);
				return value;
			} catch (Exception ex) {
				return defaultValue;
			}
		}
	}
}
